
/**
 * @author Nicolas Franzen
 * @namespace ColorDefinitionComposition -> CODECO
 */

var CODECO = CODECO || {};

CODECO.GradientMapping = function(texture, from, to){

	return {

		uniforms: {

			"tDiffuse": { type: "t", value: texture },
			"from":    { type: "c", value: from },
			"to":    { type: "c", value: to }

		},

		vertexShader: [

			"varying vec2 vUv;",

			"void main() {",

				"vUv = uv;",
				"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",

			"}"

		].join("\n"),

		fragmentShader: [

			"uniform vec3 from;",
			"uniform vec3 to;",
			"uniform sampler2D tDiffuse;",

			"varying vec2 vUv;",

			"void main() {",

				"vec4 texel = texture2D( tDiffuse, vUv );",

				"vec3 color = from.rgb * (1.0 - texel.r) + to.rgb * texel.r;",

				"gl_FragColor = vec4(color, texel.w);",

			"}"

		].join("\n")

	};

};

CODECO.changed = false;

CODECO.GradientLab = function (canvasContainerId) {
	this.canvasContainerId = canvasContainerId;
	
	var width = 800, height = 600;
	
	this.renderer;
	this.renderer = new THREE.WebGLRenderer();
	this.renderer.setSize( width, height );
	
	document.getElementById(canvasContainerId).appendChild(this.renderer.domElement);
	
	this.scene = new THREE.Scene();
	
	this.camera = new THREE.PerspectiveCamera( 70, width / height, 1, 1000 );
	this.camera.position.z = 400;
	
	
	this.colorBegin = new THREE.Color("#0000aa");
	this.colorEnd = new THREE.Color("#ffff00");
	
	this.imagePlane 	= new THREE.PlaneGeometry(360, 360  * 21.0 / 32.0, 10, 10);
	this.gradientPlane  = new THREE.PlaneGeometry(50, 500, 10, 10);
	
	this.imageTexture 		= new THREE.ImageUtils.loadTexture( 'textures/rhoneGrey.jpg' );
	this.imageTexture.anisotropy = this.renderer.getMaxAnisotropy();
	
	this.gradientTexture 	= new THREE.ImageUtils.loadTexture( 'textures/gradientGrey.png' );
	this.gradientTexture.anisotropy = this.renderer.getMaxAnisotropy();
	
	this.greyGradientMaterial	 = new THREE.MeshBasicMaterial( { map: this.gradientTexture } );
	this.colorGradientMaterial	 = new THREE.ShaderMaterial(CODECO.GradientMapping(this.gradientTexture, this.colorBegin, this.colorEnd));
	
	this.greyImageMaterial		 = new THREE.MeshBasicMaterial( { map: this.imageTexture } );
	this.colorImageMaterial		 = new THREE.ShaderMaterial(CODECO.GradientMapping(this.imageTexture, this.colorBegin, this.colorEnd));
	
	this.greyGradient 	= new THREE.Mesh(this.gradientPlane, this.greyGradientMaterial);
	this.greyGradient.position.x = 80;
	this.greyGradient.position.y = 0;
	
	
	
	this.colorGradient 	= new THREE.Mesh( this.gradientPlane, this.colorGradientMaterial);
	this.colorGradient.position.x = 140;
	this.colorGradient.position.y = 0;
	
	
	this.greyImage 		= new THREE.Mesh( this.imagePlane, this.greyImageMaterial);
	this.greyImage.position.x = -180;
	this.greyImage.position.y = +130;
	
	this.colorImage 	= new THREE.Mesh( this.imagePlane, this.colorImageMaterial);
	this.colorImage.position.x = -180;
	this.colorImage.position.y = -130;
	
	this.scene.add(this.greyGradient );
	this.scene.add(this.colorGradient);
	this.scene.add(this.greyImage );
	this.scene.add(this.colorImage );
	
	this.gui = new dat.GUI();
	this.guiData = {
		from : "#0000aa",
		to : "#ffff00"
	};
	
	var handler = this.gui.addColor( this.guiData, 'from');
	this.changer = function( colorValue  )
    {
		CODECO.changed = true;
    };
	
	handler.onChange(this.changer);
	
	
	handler = this.gui.addColor( this.guiData, 'to');
	handler.onChange(this.changer);	    
	
};

CODECO.GradientLab.prototype = {
		
		constructor : CODECO.GradientLab,
		
		update : function() {	
			if(CODECO.changed){
				CODECO.changed = false;
				this.colorBegin.set(this.guiData.from);
				this.colorEnd.set(this.guiData.to);
				this.colorGradientMaterial.uniforms.from.needsUpdate = true;
				this.colorImageMaterial.uniforms.from.needsUpdate = true;
				this.colorGradientMaterial.uniforms.to.needsUpdate = true;
				this.colorImageMaterial.uniforms.to.needsUpdate = true;
			}
		}
		
};
	